package nsga.comparison;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import foundation.dbUtil.DBException;
import foundation.dbUtil.DBUtil;
import foundation.fileUtil.DataCell;
import foundation.fileUtil.ExcelUtil;
import foundation.fileUtil.TxtFileUtil;
import nsga.comparison.util.MetricsUtil;
import weka.gui.sql.DbUtils;

public class OutResult {
	
	/**
	 * 获取所有次运行的runID，在runIDs中的顺序是先我们的方法，再PCM方法
	 * @return
	 */
	public List<String> getRunIDs(){
		List<String> runIDs = new ArrayList<String>();
		
//		PreparedStatement pStmt = null;
//		ResultSet rs = null;
//		String runID;
//		
//		String sqlTxt = "SELECT DISTINCT runID FROM t_pareto" ;
//		String dbCfgFileName = "src/foundation/dbUtil/dbConf.properties";
//		DBUtil dbUtil = DBUtil.getInstance(dbCfgFileName);
//		try {
//			pStmt = dbUtil.getPrepStmt(sqlTxt);
//			rs = pStmt.executeQuery();
//			while (rs.next()) {
//				runID = rs.getString("runID");
//				runIDs.add(runID);
//				
//			}
//		} catch (DBException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		} catch (SQLException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//		System.out.println(runIDs);
//		runIDs.add("DFGA02a88ce0-2d6b-4931-b4e9-7d1b56afdbf0");
		runIDs.add("DFGA0347d406-ab34-4efb-9ae3-95d532f311d2");
		runIDs.add("DFGA035c6fdc-51a7-4692-97a9-04f4a4d15c2d");
//		runIDs.add("DFGA042f52fe-ada2-49bf-8e7b-1f81c7ae1b0e");
		runIDs.add("DFGA0714a1d4-8309-45bc-8240-5317483bbfd7");
//		runIDs.add("DFGA09000cea-dcf2-4ead-ae96-93a2d981e7f9");
		runIDs.add("DFGA1b81f831-ce1f-4c49-a2e3-d1190e949537");
		runIDs.add("DFGA1f6368fd-15a2-4c34-83a7-adf2cf058c6e");
//		runIDs.add("DFGA212052dd-d7bb-4b0d-b184-998f871099d2");
		runIDs.add("DFGA262b2aa3-e07e-4078-b88f-f493d7e25814");
		runIDs.add("DFGA298e4266-493f-4f52-9212-245339603396");
		runIDs.add("DFGA2ab42291-03ad-4c3c-ae49-dce857d974c9");
//		runIDs.add("DFGA37a263d9-5290-41bf-a6cd-9c83481ac8a2");
		runIDs.add("DFGA4c827bd6-d176-41e0-8a51-ea25f5ac6d25");
		runIDs.add("DFGA5dc03e7c-dc27-488e-a9dd-fc969b40fe62");
//		runIDs.add("DFGA5f6f6eab-4136-41f8-af0a-236c20fde157");
//		runIDs.add("DFGA7977fec4-4193-498e-b3d1-e9c601c041ae");
//		runIDs.add("DFGA79a2bfbe-5663-4870-b373-74825e6e4fa4");
		runIDs.add("DFGAa77aeb77-ff17-48df-b06e-963b2fc4e38d");
		runIDs.add("DFGAb7ce0d30-3250-4aac-97e0-f8aa8e0c87c8");
		runIDs.add("DFGAc2c1497d-b5fe-416c-ad9d-c20b952931db");
		runIDs.add("DFGAc387a411-269d-44bb-bfed-ab16c838ecbd");
//		runIDs.add("DFGAc97147b7-9f5c-4dbf-9a16-d9745921ac9a");
		runIDs.add("DFGAcb48b5e4-475a-4192-ba4f-f1bf60e3db6f");
		runIDs.add("DFGAdd962581-e99e-4714-90b6-1ad1e0e6f6bd");
		runIDs.add("DFGAe9143eb2-3ba6-4240-b637-c376e3ea08b1");
//		runIDs.add("DFGAeb1c8166-bec4-4cc4-8fe5-d84599c5f264");
		runIDs.add("DFGAed0965c8-9176-4f0a-80bd-69806f502000");
		runIDs.add("DFGAf046a172-0e92-49d8-97bc-324d166a89a9");
		runIDs.add("DFGAf7f79693-df7b-4e32-926f-79e3b423021d");
		
		
		
//		runIDs.add("NSGA017ef99f-463b-4df5-8926-d07f6d9bd04a");
		runIDs.add("NSGA03395b03-8c21-4689-804c-31b05f383d81");
		runIDs.add("NSGA049ecea1-ec7f-4168-b31a-4c02daf7403f");
//		runIDs.add("NSGA0590bd78-c0a2-4fc1-a702-36f6baba8b48");
		runIDs.add("NSGA084a3f44-6782-4078-9b28-7521b4c89783");
//		runIDs.add("NSGA108a5bf5-783e-4b2e-8393-fe4913c1605b");
		runIDs.add("NSGA1cadba5e-5a0b-442e-874f-8a0bae3ee11c");
		runIDs.add("NSGA295b0a88-7901-47d7-b37b-30ca06481653");
//		runIDs.add("NSGA302e0c44-268c-43ee-a2e2-8aeecd503f5b");
		runIDs.add("NSGA4f9da714-cd1e-403c-8213-38d714fa2046");
		runIDs.add("NSGA558ebd5f-44ad-4e2e-adc5-d0b728099a18");
		runIDs.add("NSGA5f73bd53-3c1a-46ad-a535-9f5508fdbe0e");
//		runIDs.add("NSGA61b4c670-f438-4555-a144-4e42f2b1259a");
		runIDs.add("NSGA701f2f92-9947-4902-b150-0bf490848e68");
		runIDs.add("NSGA70c04164-8631-4ef1-bab4-d740fab58cb1");
//		runIDs.add("NSGA7d6a341f-edc0-413e-b3ae-d8ccf09e73d1");
//		runIDs.add("NSGA8563c215-fbed-4d5f-8c75-b2b56e09ad65");
//		runIDs.add("NSGA94d56513-5c4e-466f-8903-a6e957d24a6f");
		runIDs.add("NSGA981990f4-18e4-4340-98ba-108300221d7b");
		runIDs.add("NSGAa58b28a0-7870-4192-b2eb-71c2253353e2");
		runIDs.add("NSGAa639b5de-ce47-4390-b0b6-72fdd8436658");
		runIDs.add("NSGAb2b28a4d-3f2b-4382-836f-a4926b005f2f");
//		runIDs.add("NSGAd71514e4-b9f2-4fca-965f-fc6b9cca1f27");
		runIDs.add("NSGAd9e39fa4-57a1-4409-bb7f-cd21d1bf8ad4");
		runIDs.add("NSGAde72d208-4e14-41b6-81ff-39ff4ae96c84");
		runIDs.add("NSGAef1cc9c1-14c4-4918-8373-dcc6b290a8c4");
//		runIDs.add("NSGAf5ce3f1c-49d3-4920-9972-57853adc9c9b");
		runIDs.add("NSGAfabf6238-2b06-4f92-93fa-75484ff1327c");
		runIDs.add("NSGAfe2e0c6a-ba89-4347-8aa0-061e5361488e");
		runIDs.add("NSGAffce09da-b6c3-463c-9c6e-120eb2b0cb16");
		
		return runIDs;
		
//		//PCM方法
//		runIDs.add("NSGA6a7be843-8c46-43c9-95bb-e7671532cecc");
//		runIDs.add("NSGA8a52ec6d-e00e-4a03-b4de-1f36a6829c85");
//		runIDs.add("NSGA8faa1a67-8272-4a90-9f02-fa8f9dfbb5a4");
//		runIDs.add("NSGA9f0be24b-8ef2-483c-85b4-26269067b559");
//		runIDs.add("NSGAa0990cd8-2c64-4313-be32-d45459797215");
//		runIDs.add("NSGAa450207b-358a-42a7-897a-8a5ffd4d2d3d");
//		runIDs.add("NSGAaa4ec90a-2837-4849-b660-efb143e27d28");
//		runIDs.add("NSGAb16f6c97-aac9-45f7-ab92-a03941180bf6");
//		runIDs.add("NSGAb919d17a-660c-4d4c-a37d-5d5c4d4d6851");
//		runIDs.add("NSGAbfcf3d40-c571-42cc-9f43-b4b3adc98832");
//		runIDs.add("NSGAc4d2de65-7ca2-4fe5-a89c-cbcdcc89b335");
//		runIDs.add("NSGAe33e6a8e-57d9-4543-b197-a5484c4eafff");
//		runIDs.add("NSGAe8837ac0-61f8-4a25-8a64-d07d6d6700dd");
//		runIDs.add("NSGAecb45b63-96d0-41f2-9ca7-8571ba16d90e");
//		runIDs.add("NSGAed096fff-5745-4bc3-8d81-0025c4b2e89b");
//		runIDs.add("NSGAf5d5b530-9106-45b0-a8e7-c8dbfe6f4ae7");
//		runIDs.add("NSGAf77d8f5a-ad54-4721-859e-34f71bc5ed6e");
//		runIDs.add("NSGAfa0006fd-a8c0-4e14-bdfd-6f0e29a8155d");
//		runIDs.add("NSGAfb6f9cc6-74f1-4396-9b9b-697766188e63");
//		runIDs.add("NSGAfeea9346-e167-47b2-b78a-982e939bc31f");
//		return runIDs;
		
	}

	public static void main(String[] args) {
		//删除上次结果
		TxtFileUtil.deleteFile("src/nsga/comparison/", "algComparedRlt.xls");
		OutResult outResult = new OutResult();

		List<String> runIDs = outResult.getRunIDs();
		//一次运行front为所有解非支配排序，不仅仅取最后一代，genID参数最后会去掉
		String genID = "200";
		// 调用DataSource类
		DataSource ds = new DataSource();
		MetricsUtil metricUtil = new MetricsUtil();
		// 文件路径+文件名
		String myFrontFileNm = "src/nsga/comparison/MyFront.txt";
		String pcmFrontFileNm = "src/nsga/comparison/PCMFront.txt";
		// String CombiFrontFileName = "src/nsga/comparison/CombiFront.txt";
		String refFrontFileNm = "src/nsga/comparison/RefFront.txt";

		// 存储我们方法的contribution
		List<Double> contributionsOfMy = new ArrayList<Double>();
		// 存储我们方法的contribution
		List<Double> contributionsOfPCM = new ArrayList<Double>();

		// 存储我们方法的generationalDistance
		List<Double> generationalDistancesOfMy = new ArrayList<Double>();
		// 存储我们方法的generationalDistance
		List<Double> generationalDistancesOfPCM = new ArrayList<Double>();

		// 存储我们方法的hypervolume
		List<Double> hypervolumesOfMy = new ArrayList<Double>();
		// 存储我们方法的hypervolume
		List<Double> hypervolumesOfPCM = new ArrayList<Double>();

		ArrayList<ArrayList<Float>> refFront = ds.getRefFrontFront(runIDs, genID);
		metricUtil.writeToFile(refFront, refFrontFileNm);
		double[][] dblArrayOfRefFront = metricUtil.readFront(refFrontFileNm);
		// 比如PCM方法和我们方法各30次，就循环30次
		for (int i = 0; i < runIDs.size() / 2; i++) {
			// 获取被比较方法的前沿和参考前沿
			ArrayList<ArrayList<Float>> myFront = ds.getMyMethodFront(runIDs.get(i), genID);
			ArrayList<ArrayList<Float>> pcmFront = ds.getPCMMethodFront(runIDs.get(i + runIDs.size() / 2), genID);
			
			// 写入文件
			metricUtil.writeToFile(myFront, myFrontFileNm);
			metricUtil.writeToFile(pcmFront, pcmFrontFileNm);
			
			// 获取各指标输出
			double[][] dblArrayOfMyFront = metricUtil.readFront(myFrontFileNm);
			double[][] dblArrayOfPCMFront = metricUtil.readFront(pcmFrontFileNm);
			
			// contribution
			Contribution contribution = new Contribution();
			double contributionOfMy = contribution.contribution(dblArrayOfMyFront, dblArrayOfPCMFront);
			contributionsOfMy.add(contributionOfMy);
			double contributionOfPCM = 1 - contributionOfMy;
			contributionsOfPCM.add(contributionOfPCM);
			// 我们方法的世代距离
			GenerationalDistance qualityIndicator = new GenerationalDistance();
			double myValueOfGeneDistance = qualityIndicator.generationalDistance(dblArrayOfMyFront, dblArrayOfRefFront,
					new Integer(2));

			generationalDistancesOfMy.add(myValueOfGeneDistance);
			// PCM方法的世代距离
			double pcmValueOfGeneDistance = qualityIndicator.generationalDistance(dblArrayOfPCMFront,
					dblArrayOfRefFront, new Integer(2));
			generationalDistancesOfPCM.add(pcmValueOfGeneDistance);
			// 我们方法的超体积
			Hypervolume hypervolume = new Hypervolume();
			double myHyperVal = hypervolume.hypervolume(dblArrayOfMyFront, dblArrayOfRefFront, 2);
			hypervolumesOfMy.add(myHyperVal);

			// PCM方法的超体积
			double pcmHyperVal = hypervolume.hypervolume(dblArrayOfPCMFront, dblArrayOfRefFront, 2);
			hypervolumesOfPCM.add(pcmHyperVal);
		}

		// 写入到Excel中
		// sheet1:摘要（算法名1,算法1的主要参数；算法名2,算法主要参数，运行次数）
		List<List<DataCell>> algAbstract = outResult.outPara(runIDs);
		String ecxelPath = "src/nsga/comparison/algComparedRlt.xls";
		ExcelUtil.write(ecxelPath, algAbstract);
		// Sheet2:contribution指标值；{contribution指标值，（算法1名，运行次数，值）*}
		List<List<DataCell>> contributions = outResult.outIndicators(contributionsOfMy, contributionsOfPCM,
				"contrinbution");
		ExcelUtil.write(ecxelPath, contributions);
		// Sheet3:generationalDistance指标值；{generationalDistance指标值，（算法1名，运行次数，值）*}
		List<List<DataCell>> generationalDistances = outResult.outIndicators(generationalDistancesOfMy,
				generationalDistancesOfPCM, "generationalDistance");
		ExcelUtil.write(ecxelPath, generationalDistances);
		// Sheet4:generationalDistance指标值；{generationalDistance指标值，（算法1名，运行次数，值）*}
		List<List<DataCell>> hypervolumes = outResult.outIndicators(hypervolumesOfMy, hypervolumesOfPCM,
				"hypervolume");
		ExcelUtil.write(ecxelPath, hypervolumes);

	}
	

	/**
	 * 将计算的结果输出到excel
	 * @param indicators1：我们方法的值
	 * @param indicators2：PCM方法的值
	 * @param indicatorName：哪一个度量指标
	 * @return
	 */
	public List<List<DataCell>> outIndicators(List<Double> indicators1, List<Double> indicators2,
			String indicatorName) {
		List<List<DataCell>> rlts = new ArrayList<List<DataCell>>();
		// 输出:运行次数,算法1名，算法2名 的格式
		List<DataCell> rows = new ArrayList<DataCell>();
		DataCell numCell = new DataCell();
		numCell.setName("次数");
		rows.add(numCell);
		DataCell myCell = new DataCell();
//		myCell.setName(indicatorName + "OfNSRulSeqGA");
		myCell.setName(indicatorName + "OfSM");
		rows.add(myCell);
		DataCell pcmCell = new DataCell();
		pcmCell.setName(indicatorName + "OfPCM");
//		pcmCell.setName(indicatorName + "OfSM");
		rows.add(pcmCell);
		rlts.add(rows);
		for (int i = 0; i < indicators1.size(); i++) {
			List<DataCell> oneRow = new ArrayList<DataCell>();
			DataCell numDataCell = new DataCell();
			numDataCell.setName("第" + i + "次");
			oneRow.add(numDataCell);
			DataCell myDataCell = new DataCell();
			myDataCell.setName(String.valueOf(indicators1.get(i)));
			oneRow.add(myDataCell);
			DataCell pcmDataCell = new DataCell();
			pcmDataCell.setName(String.valueOf(indicators2.get(i)));
			oneRow.add(pcmDataCell);
			rlts.add(oneRow);
		}
		return rlts;
	}

	/**
	 * 输出算法摘要
	 * @param runIDs
	 * @return
	 */
	public List<List<DataCell>> outPara(List<String> runIDs) {
		List<List<DataCell>> paraRows = new ArrayList<List<DataCell>>();
		// 设置caseName行
		List<DataCell> caseNameRow = new ArrayList<DataCell>();
		DataCell caseNameDataCell = new DataCell();
		caseNameDataCell.setName("caseName");
		caseNameDataCell.setValue("jssbrs");
		caseNameRow.add(caseNameDataCell);
		paraRows.add(caseNameRow);
		// 设置算法名行
		List<DataCell> alg1 = new ArrayList<DataCell>();
		DataCell algDataCell = new DataCell();
		algDataCell.setName("alg1");
		algDataCell.setValue("NSRulSeqGA");
		alg1.add(algDataCell);
		paraRows.add(alg1);
		// 设置种群行
		List<DataCell> popuSizeRow = new ArrayList<DataCell>();
		DataCell popuSizeDataCell = new DataCell();
		popuSizeDataCell.setName("PopuSize");
		popuSizeDataCell.setValue("30");
		popuSizeRow.add(popuSizeDataCell);
		paraRows.add(popuSizeRow);
		// 迭代次数
		List<DataCell> maxIterNumRow = new ArrayList<DataCell>();
		DataCell maxIterNumDataCell = new DataCell();
		maxIterNumDataCell.setName("maxIterNum");
		maxIterNumDataCell.setValue("200");
		maxIterNumRow.add(maxIterNumDataCell);
		paraRows.add(maxIterNumRow);
		// 变异概率
		List<DataCell> mutateProbRow = new ArrayList<DataCell>();
		DataCell mutateProbDataCell = new DataCell();
		mutateProbDataCell.setName("mutateProb");
		mutateProbDataCell.setValue("0.3");
		mutateProbRow.add(mutateProbDataCell);
		paraRows.add(mutateProbRow);
		// 交叉概率
		List<DataCell> crossProbRow = new ArrayList<DataCell>();
		DataCell crossProbDataCell = new DataCell();
		crossProbDataCell.setName("crossProb");
		crossProbDataCell.setValue("0.8");
		crossProbRow.add(crossProbDataCell);
		paraRows.add(crossProbRow);
		// 运行次数
		List<DataCell> runNumRow = new ArrayList<DataCell>();
		DataCell runNumDataCell = new DataCell();
		runNumDataCell.setName("runNums");
		runNumDataCell.setValue(String.valueOf(runIDs.size() / 2));
		runNumRow.add(runNumDataCell);
		paraRows.add(runNumRow);

		// 空一行
		List<DataCell> empty = new ArrayList<DataCell>();
		paraRows.add(empty);
		// 设置caseName行
		paraRows.add(caseNameRow);
		// 设置算法名行
		List<DataCell> alg2 = new ArrayList<DataCell>();
		DataCell algDataCell2 = new DataCell();
		algDataCell2.setName("alg2");
		algDataCell2.setValue("PCM");
		alg2.add(algDataCell2);
		paraRows.add(alg2);
		// 设置种群行
		paraRows.add(popuSizeRow);
		// 迭代次数
		paraRows.add(maxIterNumRow);
		// 变异概率
		List<DataCell> mutateProbRow2 = new ArrayList<DataCell>();
		DataCell mutateProbDataCell2 = new DataCell();
		mutateProbDataCell2.setName("mutateProb");
		mutateProbDataCell2.setValue("0.6");
		mutateProbRow2.add(mutateProbDataCell2);
		paraRows.add(mutateProbRow2);
		// 交叉概率
		paraRows.add(crossProbRow);
		// 运行次数
		paraRows.add(runNumRow);

		return paraRows;
	}

}
